package com.cn.server.websocket;

import com.cn.common.module.ModuleId;
import com.cn.common.module.chat.ChatCmd;
import com.cn.common.module.login.UserCmd;
import com.cn.server.handler.websocket.WebSocketSingleChatHandler;
import com.cn.server.handler.websocket.WebSocketLoginHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
import org.springframework.stereotype.Component;

/**
 * netty服务端
 */
@Component
public class WebSocketServer {

    private WebSocketMessageDispatcher webSocketMessageDispatcher = new WebSocketMessageDispatcher();


    public WebSocketServer registerHandlers() {
        webSocketMessageDispatcher.register(ModuleId.USER, UserCmd.LOGIN, new WebSocketLoginHandler());
        webSocketMessageDispatcher.register(ModuleId.CHAT, ChatCmd.PRIVATE_CHAT, new WebSocketSingleChatHandler());
        return this;
    }

    private int port;

    public WebSocketServer setPort(int port) {
        this.port = port;
        return this;
    }

    /**
     * 启动
     */
    public void start() {

        // 服务类
        ServerBootstrap b = new ServerBootstrap();

        // 创建boss和worker
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 设置循环线程组事例
            b.group(bossGroup, workerGroup);

            // 设置channel工厂
            b.channel(NioServerSocketChannel.class);

            // 设置管道
            b.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    // 设置30秒没有读到数据，则触发一个READER_IDLE事件。
                    // pipeline.addLast(new IdleStateHandler(30, 0, 0));
                    // HttpServerCodec：将请求和应答消息解码为HTTP消息
                    ch.pipeline().addLast("http-codec", new HttpServerCodec());
                    // HttpObjectAggregator：将HTTP消息的多个部分合成一条完整的HTTP消息
                    ch.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
                    // ChunkedWriteHandler：向客户端发送HTML5文件
                    ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
                    // 在管道中添加我们自己的接收数据实现方法
                    ch.pipeline().addLast("handler", new WebSocketServerHandler(webSocketMessageDispatcher));
                }
            });

            b.option(ChannelOption.SO_BACKLOG, 2048);// 链接缓冲池队列大小

            // 绑定端口
            b.bind(10102).sync();

            System.out.println("simple websocket chat start!!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
